package com.zzx.interceptor;

import com.zzx.common.exception.ServiceException;
import com.zzx.config.UserContext;
import com.zzx.utils.JWTUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * @Author: zzx
 * @Date: 2025/4/12 20:04
 */
@Slf4j
public class AuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        String uri = request.getRequestURI();
        log.debug("拦截请求: {} {}", request.getMethod(), uri);

        // 1. 放行Knife4j相关请求
        if (uri.contains("/v3/api-docs") || uri.contains("/doc.html")) {
            return true;
        }

        String token = request.getHeader("X-Token");
        if (ObjectUtils.isEmpty(token)) {
            throw new ServiceException("请求头缺少 X-Token");
        }

        try {
            // 2. 验证 Token
            if (!JWTUtil.verifyToken(token)) {
                throw new ServiceException("Token 验证失败");
            }
            
            // 3. 解析 Token
            Map<String, Object> claims = JWTUtil.getTokenInfo(token);
            
            // 4. 将用户信息存入 ThreadLocal
            UserContext.setCurrentUser(claims);
            
            log.debug("用户认证成功 - userId: {}, companyId: {}", 
                    UserContext.getUserId(), UserContext.getCompanyId());
            
        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("Token 解析异常: {}", e.getMessage());
            throw new ServiceException("Token 无效或已过期");
        }
        
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 请求结束后清理 ThreadLocal，防止内存泄漏
        UserContext.clear();
    }
}
